// Modbus功能码
const ModbusFunction = {
  READ_COILS: 0x01,
  READ_DISCRETE_INPUTS: 0x02,
  READ_HOLDING_REGISTERS: 0x03,
  READ_INPUT_REGISTERS: 0x04,
  WRITE_SINGLE_COIL: 0x05,
  WRITE_SINGLE_REGISTER: 0x06,
  WRITE_COILS: 0x0F,
  WRITE_HOLDING_REGISTERS: 0x10
}

// Modbus错误类型
const ModbusErrorType = {
  ModbusInvalidArgumentError: 'Invalid argument',
  ModbusFunctionNotSupportedError: 'Function not supported',
  ModbusResponseError: 'Invalid response'
}

// Modbus错误类
class ModbusError extends Error {
  constructor(type, message) {
    super(message)
    this.type = type
    this.name = 'ModbusError'
  }
}

// CRC16计算
function calculateCRC16(buffer) {
  let crc = 0xFFFF
  for (let i = 0; i < buffer.length; i++) {
    crc ^= buffer[i]
    for (let j = 0; j < 8; j++) {
      if (crc & 0x0001) {
        crc = (crc >> 1) ^ 0xA001
      } else {
        crc = crc >> 1
      }
    }
  }
  return crc
}

// 将数字转换为字节数组
function numberToBytes(number, length) {
  const bytes = new ArrayBuffer(length)
  const view = new DataView(bytes)
  if (length === 1) {
    view.setUint8(0, number)
  } else if (length === 2) {
    view.setUint16(0, number, false)
  } else if (length === 4) {
    view.setUint32(0, number, false)
  }
  return new Uint8Array(bytes)
}

// 组装Modbus RTU消息帧
function buildModbusFrame(slave, functionCode, startingAddress, quantity, data = null) {
  if (slave < 0 || slave > 0xFF) {
    throw new ModbusError(ModbusErrorType.ModbusInvalidArgumentError, 'Invalid slave address')
  }
  if (startingAddress < 0 || startingAddress > 0xFFFF) {
    throw new ModbusError(ModbusErrorType.ModbusInvalidArgumentError, 'Invalid starting address')
  }
  if (quantity < 1 || quantity > 0xFF) {
    throw new ModbusError(ModbusErrorType.ModbusInvalidArgumentError, 'Invalid quantity')
  }

  let frame = []
  frame.push(slave)
  frame.push(functionCode)
  frame.push(...numberToBytes(startingAddress, 2))
  frame.push(...numberToBytes(quantity, 2))

  if (data) {
    if (Array.isArray(data)) {
      frame.push(data.length * 2)
      data.forEach(value => {
        frame.push(...numberToBytes(value, 2))
      })
    } else {
      frame.push(...numberToBytes(data, 2))
    }
  }

  const crc = calculateCRC16(new Uint8Array(frame))
  frame.push(crc & 0xFF)
  frame.push((crc >> 8) & 0xFF)

  return new Uint8Array(frame)
}

// 解析Modbus响应
function parseModbusResponse(response, functionCode) {
  if (!response || response.length < 3) {
    throw new ModbusError(ModbusErrorType.ModbusResponseError, 'Invalid response length')
  }

  // 检查从站地址和功能码
  if (response[0] !== response[0] || response[1] !== functionCode) {
    throw new ModbusError(ModbusErrorType.ModbusResponseError, 'Invalid response header')
  }

  // 检查CRC
  const receivedCRC = (response[response.length - 1] << 8) | response[response.length - 2]
  const calculatedCRC = calculateCRC16(response.slice(0, -2))
  if (receivedCRC !== calculatedCRC) {
    throw new ModbusError(ModbusErrorType.ModbusResponseError, 'CRC check failed')
  }

  return response
}

// Modbus RTU命令生成函数
const ModbusRTU = {
  // 读线圈寄存器
  readCoils(slave, startAddress, quantity) {
    return buildModbusFrame(slave, ModbusFunction.READ_COILS, startAddress, quantity)
  },

  // 读离散输入寄存器
  readDiscreteInputs(slave, startAddress, quantity) {
    return buildModbusFrame(slave, ModbusFunction.READ_DISCRETE_INPUTS, startAddress, quantity)
  },

  // 读保持寄存器
  readHoldingRegisters(slave, startAddress, quantity) {
    return buildModbusFrame(slave, ModbusFunction.READ_HOLDING_REGISTERS, startAddress, quantity)
  },

  // 读输入寄存器
  readInputRegisters(slave, startAddress, quantity) {
    return buildModbusFrame(slave, ModbusFunction.READ_INPUT_REGISTERS, startAddress, quantity)
  },

  // 写单个线圈
  writeSingleCoil(slave, address, value) {
    return buildModbusFrame(slave, ModbusFunction.WRITE_SINGLE_COIL, address, 1, value ? 0xFF00 : 0x0000)
  },

  // 写单个寄存器
  writeSingleRegister(slave, address, value) {
    return buildModbusFrame(slave, ModbusFunction.WRITE_SINGLE_REGISTER, address, 1, value)
  },

  // 写多个线圈
  writeCoils(slave, address, values) {
    return buildModbusFrame(slave, ModbusFunction.WRITE_COILS, address, values.length, values)
  },

  // 写多个寄存器
  writeHoldingRegisters(slave, address, values) {
    return buildModbusFrame(slave, ModbusFunction.WRITE_HOLDING_REGISTERS, address, values.length, values)
  },

  // 解析响应
  parseResponse(response, functionCode) {
    return parseModbusResponse(response, functionCode)
  }
}

// 数据解析工具函数
const ByteUtil = {
  // 字节转16位有符号整数
  bytesToInt16(byte1, byte2) {
    const value = (byte1 << 8) | byte2
    return (value & 0x8000) ? value - 0x10000 : value
  },

  // 字节转16位无符号整数
  bytesToUint16(byte1, byte2) {
    return ((byte1 << 8) | byte2) >>> 0
  },

  // 字节转32位无符号整数
  bytesToUint32(byte1, byte2, byte3, byte4) {
    return ((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4) >>> 0
  },

  // 从字节数组解析16位有符号整数
  parseInt16FromArray(array, index) {
    return this.bytesToInt16(array[index * 2], array[index * 2 + 1])
  },

  // 从字节数组解析16位无符号整数
  parseUint16FromArray(array, index) {
    return this.bytesToUint16(array[index * 2], array[index * 2 + 1])
  },

  // 从字节数组解析32位无符号整数
  parseUint32FromArray(array, index) {
    return this.bytesToUint32(array[index * 2], array[index * 2 + 1], array[index * 2 + 2], array[index * 2 + 3])
  }
}

function arrayBufferToArray(arrayBuffer) {
  const typedArray = new Uint8Array(arrayBuffer);
  const array = [];
  for (let i = 0; i < typedArray.length; i++) {
    array.push(typedArray[i]);
  }
  return array;
}


// int32转4字节大端
function int32ToBytes(num) {
  const arr = new Uint8Array(4);
  arr[0] = (num >> 24) & 0xFF;
  arr[1] = (num >> 16) & 0xFF;
  arr[2] = (num >> 8) & 0xFF;
  arr[3] = num & 0xFF;
  return arr;
}

module.exports = {
  ModbusFunction,
  ModbusErrorType,
  ModbusError,
  ModbusRTU,
  ByteUtil,
  arrayBufferToArray,
  int32ToBytes
} 